library(tidyverse)
library(tidyr)
library(ggplot2)
library(dplyr)
library(RColorBrewer)
games_sales_full <- read_csv("games_sales_full_cleaned.csv")
Missing column names filled in: 'X1' [1]Parsed with column specification:
cols(
  .default = col_double(),
  name = col_character(),
  genre = col_character(),
  esrb_rating = col_character(),
  platform = col_character(),
  publisher = col_character(),
  developer = col_character(),
  last_update = col_character()
)
See spec(...) for full column specifications.
games_sales_full_total <- read_csv("games_sales_full_total_cleaned.csv")
Missing column names filled in: 'X1' [1]Parsed with column specification:
cols(
  .default = col_double(),
  name = col_character(),
  genre = col_character(),
  esrb_rating = col_character(),
  platform = col_character(),
  publisher = col_character(),
  developer = col_character(),
  last_update = col_character()
)
See spec(...) for full column specifications.

Due to the size of the file I will focuson on the top sales for analysis

games_sales_full_total_top_200 <- games_sales_full_total %>%
  arrange(desc(total_global_sales)) %>%
  slice(1:200)
games_sales_full_total_top_200
games_sales_full_total_top_50 <- games_sales_full_total %>%
  arrange(desc(total_global_sales)) %>%
  slice(1:50)
games_sales_full_total_top_50
summary(games_sales_full_total)
       X1             rank           name              genre           esrb_rating          platform          publisher          developer          critic_score     user_score    total_shipped_2019
 Min.   :    1   Min.   :    1   Length:55792       Length:55792       Length:55792       Length:55792       Length:55792       Length:55792       Min.   : 1.00   Min.   : 2.00   Min.   : 0.0000   
 1st Qu.:13949   1st Qu.:13949   Class :character   Class :character   Class :character   Class :character   Class :character   Class :character   1st Qu.: 6.40   1st Qu.: 7.80   1st Qu.: 0.0000   
 Median :27896   Median :27896   Mode  :character   Mode  :character   Mode  :character   Mode  :character   Mode  :character   Mode  :character   Median : 7.50   Median : 8.50   Median : 0.0000   
 Mean   :27896   Mean   :27896                                                                                                                     Mean   : 7.21   Mean   : 8.25   Mean   : 0.0618   
 3rd Qu.:41844   3rd Qu.:41844                                                                                                                     3rd Qu.: 8.30   3rd Qu.: 9.10   3rd Qu.: 0.0000   
 Max.   :55792   Max.   :55792                                                                                                                     Max.   :10.00   Max.   :10.00   Max.   :82.8600   
                                                                                                                                                   NA's   :49256   NA's   :55457                     
 global_sales_2019 na_sales_2019   eu_sales_2019   jp_sales_2019   other_sales_2019      year      last_update        vgchartzscore   na_sales_2016   eu_sales_2016   jp_sales_2016   other_sales_2016
 Min.   : 0.0000   Min.   :0.00    Min.   :0.00    Min.   :0.00    Min.   :0.00     Min.   :1970   Length:55792       Min.   :2.60    Min.   :0.00    Min.   :0.00    Min.   :0.00    Min.   :0.00    
 1st Qu.: 0.0000   1st Qu.:0.05    1st Qu.:0.01    1st Qu.:0.02    1st Qu.:0.00     1st Qu.:2000   Class :character   1st Qu.:6.80    1st Qu.:0.03    1st Qu.:0.00    1st Qu.:0.00    1st Qu.:0.00    
 Median : 0.0000   Median :0.12    Median :0.04    Median :0.05    Median :0.01     Median :2008   Mode  :character   Median :7.80    Median :0.09    Median :0.01    Median :0.00    Median :0.01    
 Mean   : 0.1272   Mean   :0.28    Mean   :0.16    Mean   :0.11    Mean   :0.04     Mean   :2006                      Mean   :7.43    Mean   :0.14    Mean   :0.06    Mean   :0.01    Mean   :0.02    
 3rd Qu.: 0.0400   3rd Qu.:0.29    3rd Qu.:0.14    3rd Qu.:0.12    3rd Qu.:0.04     3rd Qu.:2011                      3rd Qu.:8.50    3rd Qu.:0.18    3rd Qu.:0.05    3rd Qu.:0.00    3rd Qu.:0.02    
 Max.   :20.3200   Max.   :9.76    Max.   :9.85    Max.   :2.69    Max.   :3.12     Max.   :2020                      Max.   :9.60    Max.   :1.22    Max.   :1.23    Max.   :0.81    Max.   :0.25    
                   NA's   :42828   NA's   :42603   NA's   :48749   NA's   :40270    NA's   :979                       NA's   :54993   NA's   :55238   NA's   :55238   NA's   :55238   NA's   :55238   
 global_sales_2016  total_global_sales
 Min.   :0.000000   Min.   : 0.0000   
 1st Qu.:0.000000   1st Qu.: 0.0000   
 Median :0.000000   Median : 0.0000   
 Mean   :0.002245   Mean   : 0.1912   
 3rd Qu.:0.000000   3rd Qu.: 0.0700   
 Max.   :2.150000   Max.   :82.8600   
                                      
1. Use graph
games_sales_full_total_top_200 %>%
  group_by(genre) %>% 
  ggplot(aes(x = genre, fill = genre) ) +
  geom_bar() +
  labs(title = "Games count by genre") +
  labs(x = "Genre") +
  labs(y = "Number of Games") +
  labs(fill = "Genre") +
  coord_flip()

games_sales_full_total_top_200 %>%
  group_by(genre) %>% 
  ggplot(aes(x = genre, fill = genre) ) +
  geom_bar() +
  theme(legend.position="none") +
  labs(title = "Games count by genre") +
  labs(x = "Genre") +
  labs(y = "Number of Games") +
  labs(fill = "Genre") +
  coord_flip()
ggsave("genre_count.png")
Saving 7.29 x 4.51 in image

2. Use graph ????
games_sales_full_total_top_200 %>% 
  group_by(publisher) %>% 
  ggplot(aes(x = genre, fill = publisher) ) +
  geom_bar() +
  labs(title = "Games count by publisher and genre") +
  labs(x = "Genre") +
  labs(y = "Number of Games") +
  labs(fill = "Publisher") +
  coord_flip()

games_sales_full_total_top_200 %>% 
  group_by(developer) %>% 
  ggplot(aes(x = genre, fill = developer) ) +
  geom_bar() +
  labs(title = "Games count by developer and genre") +
  labs(x = "Genre") +
  labs(y = "Number of Games") +
  labs(fill = "Developer") +
  coord_flip()

games_sales_full_total_top <- games_sales_full_total %>%
  arrange(desc(total_global_sales)) %>%
  slice(1:50)
games_sales_full_total_top
NA
3. Use graph
games_sales_full_total_top %>% 
  group_by(developer) %>% 
  ggplot(aes(x = genre, fill = developer) ) +
  geom_bar() +
  labs(title = "Games count by developer and genre") +
  labs(x = "Genre") +
  labs(y = "Number of Games") +
  labs(fill = "Developer") +
  coord_flip()
ggsave("genre_developer.png")
Saving 7.29 x 4.51 in image

3.5 Use graph - Genre and Dev flipped
games_sales_full_total_top %>% 
  group_by(developer) %>% 
  ggplot(aes(x = developer, fill = genre) ) +
  geom_bar() +
  labs(title = "Games count by developer and genre") +
  labs(x = "Developer") +
  labs(y = "Number of Games") +
  labs(fill = "Genre") +
  coord_flip()
ggsave("developer_genre.png")
Saving 7.29 x 4.51 in image

games_sales_full_total_top_games <- games_sales_full_total %>%
  arrange(desc(total_global_sales)) %>%
  slice(1:20)
games_sales_full_total_top_games
4. Use graph
games_sales_full_total_top_games %>% 
  group_by(name) %>% 
  ggplot(aes(x = name, y = total_global_sales, fill = name)) +
  geom_col() +
  labs(title = "Top 20 games sales by name") +
  labs(x = "Name") +
  labs(y = "Top 20 global sales") +
  labs(fill = "Name") +
  coord_flip()
ggsave("top20_games.png")
Saving 7.29 x 4.51 in image

games_sales_full_total_top_games %>% 
  group_by(name) %>% 
  ggplot(aes(x = name, y = total_global_sales, fill = name)) +
  geom_col() +
  theme(legend.position="none") +
  labs(title = "Top 20 games sales by name") +
  labs(x = "Name") +
  labs(y = "Top 20 global sales") +
  labs(fill = "Name") +
  coord_flip()
ggsave("top20_games.png")
Saving 7.29 x 4.51 in image

games_sales_full_total_top_games_genre <- games_sales_full_total %>%
  arrange(desc(total_global_sales)) %>%
  slice(1:40)
games_sales_full_total_top_games_genre
games_sales_full_total_top_games_genre_select <- games_sales_full_total %>%
  arrange(desc(total_global_sales)) %>%
  select(rank, name, genre, platform, total_global_sales) %>%
  slice(1:50)
games_sales_full_total_top_games_genre_select
games_sales_full_total_top_games_genre %>% 
  group_by(name) %>% 
  ggplot(aes(x = name, y = total_global_sales, fill = genre)) +
  geom_col() +
  labs(title = "Top 40 games sales by name and genre") +
  labs(x = "Name") +
  labs(y = "Top 40 global sales") +
  labs(fill = "Genre") +
  coord_flip()
ggsave("top40_games_name_genre.png")
Saving 7.29 x 4.51 in image

k-means

#games_sales_full_total_top_games_genre %>% 
 # unnest(cols = c(augmented)) %>%
  #filter(k == 2) %>%
# ggplot(aes(x = murder, y = assault, colour = .cluster, label = .rownames)) +
 # geom_point(aes(color = .cluster)) +
 # geom_text(hjust = 0, vjust = - 0.5, size = 3)
5. Use graph
games_sales_full_total_top_200 %>% 
  group_by(developer) %>% 
  ggplot(aes(x = genre, fill = platform)) +
  geom_bar() +
  labs(title = "Games count by platform and genre") +
  labs(x = "Genre") +
  labs(y = "Number of Games") +
  labs(fill = "Platform") +
  coord_flip()
ggsave("count_platform_genre.png")
Saving 7.29 x 4.51 in image

6. Use graph - graph 5. swapped use 5 OR 6
games_sales_full_total_top_200 %>% 
  group_by(developer) %>% 
  ggplot(aes(x = platform, fill = genre)) +
  geom_bar() +
  labs(title = "Games count by genre and platform") +
  labs(x = "Platform") +
  labs(y = "Number of Games") +
  labs(fill = "Genre") +
  coord_flip()
ggsave("count_genre_platform.png")
Saving 7.29 x 4.51 in image

Already used as graph 1

games_sales_full_total_top_200 %>% 
  group_by(genre) %>% 
  ggplot(aes(x = genre, fill = genre)) +
  geom_bar() +
  labs(title = "Games count by genre") +
  labs(x = "Genre") +
  labs(y = "Number of Games") +
  labs(fill = "Genre") +
  coord_flip()
ggsave("genre_count.png")
Saving 7.29 x 4.51 in image

Games by platform

games_sales_full_total_top_200 %>% 
  group_by(genre) %>% 
  ggplot(aes(x = platform, fill = platform) ) +
  geom_bar() +
  labs(title = "Games count by Platform") +
  labs(x = "Platform") +
  labs(y = "Number of Games") +
  labs(fill = "Platform") +
  coord_flip()

7. Use graph
games_sales_full_total_top_200 %>% 
  group_by(genre) %>% 
  ggplot(aes(x = platform, fill = platform) ) +
  geom_bar() +
  theme(legend.position="none") +
  labs(title = "Games count by Platform") +
  labs(x = "Platform") +
  labs(y = "Number of Games") +
  labs(fill = "Platform") +
  coord_flip()
ggsave("platform_count.png")
Saving 7.29 x 4.51 in image

Games by region - global market

games_sales_full_longer %>% 
  group_by(genre) %>% 
  ggplot(aes(x = sales_region, y = sales_region_millions) ) +
  geom_line() +
  labs(title = "Geographic breakdown of Global Sales") +
  labs(x = "Specific global market") +
  labs(y = "Sales (millions)") +
  labs(fill = "Genre") +
  coord_flip()

games_sales_full_total_top_200 %>% 
  group_by(genre) %>% 
  ggplot(aes(x = total_global_sales, fill = genre) ) +
  geom_bar() +
  labs(title = "Geographic breakdown of Global Sales") +
  labs(x = "Sales (millions)") +
  labs(y = "Specific global market") +
  labs(fill = "Genre") +
  coord_flip()

Hide the legend

games_sales_full_total_top_200 %>% 
  group_by(genre) %>% 
  ggplot(aes(x = total_global_sales, fill = genre)) +
  geom_bar() +
  theme(legend.position="none") +
  labs(title = "Geographic breakdown of Global Sales") +
  labs(x = "Sales (millions)") +
  labs(y = "Specific global market") +
  labs(fill = "Genre") +
  coord_flip()

games_sales_full_total_top_200 %>% 
  gather("id", "value", 13:16) %>% 
  ggplot(., aes(total_global_sales, value))+
  geom_point()+
  geom_smooth(method = "lm", se=FALSE, color="black")+
  facet_wrap(~id)

games_sales_full_longer <- read_csv("games_sales_full_longer.csv")
Missing column names filled in: 'X1' [1]Duplicated column names deduplicated: 'X1' => 'X1_1' [2]Parsed with column specification:
cols(
  .default = col_double(),
  name = col_character(),
  genre = col_character(),
  esrb_rating = col_character(),
  platform = col_character(),
  publisher = col_character(),
  developer = col_character(),
  last_update = col_character(),
  na_sales_2016 = col_logical(),
  eu_sales_2016 = col_logical(),
  jp_sales_2016 = col_logical(),
  other_sales_2016 = col_logical(),
  sales_region = col_character()
)
See spec(...) for full column specifications.
6100 parsing failures.
 row              col           expected actual                          file
4441 na_sales_2016    1/0/T/F/TRUE/FALSE   1.21 'games_sales_full_longer.csv'
4441 eu_sales_2016    1/0/T/F/TRUE/FALSE   0.75 'games_sales_full_longer.csv'
4441 other_sales_2016 1/0/T/F/TRUE/FALSE   0.19 'games_sales_full_longer.csv'
4442 na_sales_2016    1/0/T/F/TRUE/FALSE   1.21 'games_sales_full_longer.csv'
4442 eu_sales_2016    1/0/T/F/TRUE/FALSE   0.75 'games_sales_full_longer.csv'
.... ................ .................. ...... .............................
See problems(...) for more details.
games_sales_full_bind_total_longer <- read_csv("games_sales_full_bind_total_longer.csv")
Missing column names filled in: 'X1' [1]Parsed with column specification:
cols(
  X1 = col_double(),
  name = col_character(),
  platform = col_character(),
  genre = col_character(),
  publisher = col_character(),
  global_sales = col_double(),
  critic_score = col_double(),
  developer = col_character(),
  year_data = col_double(),
  rank = col_logical(),
  esrb_rating = col_logical(),
  user_score = col_logical(),
  total_shipped = col_logical(),
  year = col_logical(),
  last_update = col_logical(),
  vgchartzscore = col_logical(),
  total_global_sales = col_logical(),
  sales_region = col_character(),
  sales_region_millions = col_double()
)
560728 parsing failures.
  row           col           expected actual                                     file
66877 esrb_rating   1/0/T/F/TRUE/FALSE  E     'games_sales_full_bind_total_longer.csv'
66877 total_shipped 1/0/T/F/TRUE/FALSE  82.86 'games_sales_full_bind_total_longer.csv'
66877 year          1/0/T/F/TRUE/FALSE  2006  'games_sales_full_bind_total_longer.csv'
66878 esrb_rating   1/0/T/F/TRUE/FALSE  E     'games_sales_full_bind_total_longer.csv'
66878 total_shipped 1/0/T/F/TRUE/FALSE  82.86 'games_sales_full_bind_total_longer.csv'
..... ............. .................. ...... ........................................
See problems(...) for more details.
games_sales_full_bind_total_longer %>%
  group_by(sales_region, year_data) %>%
  summarise(Total = sum(sales_region_millions, na.rm = TRUE))
`summarise()` regrouping output by 'sales_region' (override with `.groups` argument)
games_sales_full_bind_total_longer %>%
  group_by(sales_region, year_data) %>%
  summarise(Total = sum(sales_region_millions, na.rm = TRUE)) %>%
  ggplot(aes(x = sales_region, y = Total)) +
  geom_bar(stat = "identity") +
  labs(title = "Total gobal sales by region") +
  labs(x = "Global market region") +
  labs(y = "Total sales (millions)") +
  facet_wrap(~year_data)
`summarise()` regrouping output by 'sales_region' (override with `.groups` argument)

ggplot(games_sales_full_bind_total_longer, aes(sales_region, sales_region_millions)) +
  geom_boxplot() +
  labs(title = "Distribution of sales by genre") +
  labs(x = "Genre") +
  labs(y = "Sales (millions)") +
   coord_flip()

8. Use graph
games_sales_full_bind_total_longer_region %>%
  ggplot(aes(x = sales_region, y = sales_region_millions)) +
  geom_col() +
  labs(title = "Total gobal sales by region") +
  labs(x = "Global market region") +
  labs(y = "Total sales (millions)") +
  scale_fill_brewer () +
  facet_wrap(~year_data)

games_sales_full_bind_total<- read_csv("games_sales_full_bind_total.csv")
Missing column names filled in: 'X1' [1]Parsed with column specification:
cols(
  .default = col_double(),
  name = col_character(),
  platform = col_character(),
  genre = col_character(),
  publisher = col_character(),
  developer = col_character(),
  rank = col_logical(),
  esrb_rating = col_logical(),
  user_score = col_logical(),
  total_shipped = col_logical(),
  year = col_logical(),
  last_update = col_logical(),
  vgchartzscore = col_logical(),
  total_global_sales = col_logical()
)
See spec(...) for full column specifications.
140182 parsing failures.
  row           col           expected actual                              file
16720 esrb_rating   1/0/T/F/TRUE/FALSE  E     'games_sales_full_bind_total.csv'
16720 total_shipped 1/0/T/F/TRUE/FALSE  82.86 'games_sales_full_bind_total.csv'
16720 year          1/0/T/F/TRUE/FALSE  2006  'games_sales_full_bind_total.csv'
16721 rank          1/0/T/F/TRUE/FALSE  2     'games_sales_full_bind_total.csv'
16721 total_shipped 1/0/T/F/TRUE/FALSE  40.24 'games_sales_full_bind_total.csv'
..... ............. .................. ...... .................................
See problems(...) for more details.
Dont use
games_sales_full_bind_total_longer %>%
  ggplot(aes(x = sales_region, y = sales_region_millions, fill = genre)) +
  geom_col() +
  labs(title = "Total global sales by region") +
  labs(x = "Total sales") +
  labs(y = "Global market region")
ggsave("sales_region_genre.png")
Saving 7.29 x 4.51 in image

XXXXXXXX WRONG DS

games_sales_full_bind_total_longer %>%
  ggplot(aes(x = genre, y = sales_region_millions, fill = sales_region)) +
  geom_col() +
  labs(title = "Total global sales by genre and region") +
  labs(x = "Global market region") +
  labs(y = "Total sales") +
  coord_flip()
ggsave("sales_genre_region.png")
Saving 7.29 x 4.51 in image

Correct DS

games_sales_full_bind_total_longer %>%
  group_by(sales_region, year_data, genre, sales_region_millions) %>%
  summarise(Total = sum(sales_region_millions, na.rm = TRUE)) %>%
  ggplot(aes(x = genre, y = sales_region_millions, fill = sales_region)) +
  geom_col() +
  labs(title = "Total global sales by genre and region") +
  labs(x = "Global market region") +
  labs(y = "Total sales") +
  coord_flip()
`summarise()` regrouping output by 'sales_region', 'year_data', 'genre' (override with `.groups` argument)
ggsave("sales_genre_region.png")
Saving 7.29 x 4.51 in image

9. Use graph

Games mean (max/ min) sales

ggplot(games_sales_full_total_top_200, aes(genre, total_global_sales)) +
  geom_boxplot() +
  labs(title = "Distribution of sales by genre") +
  labs(x = "Genre") +
  labs(y = "Sales (millions)") +
   coord_flip()
ggsave("distribution_sales_by_genre.png")
Saving 7.29 x 4.51 in image

10. Use graph
ggplot(games_sales_full_total_top_200, aes(platform, total_global_sales)) +
  geom_boxplot() +
  labs(title = "Distribution of sales by platform") +
  labs(x = "Platform") +
  labs(y = "Sales (millions)") +
   coord_flip()
ggsave("distribution_sales_by_platform.png")
Saving 7.29 x 4.51 in image

shipped / critic score

LS0tCnRpdGxlOiAiUiBOb3RlYm9vayIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKYGBge3J9CmxpYnJhcnkodGlkeXZlcnNlKQpsaWJyYXJ5KHRpZHlyKQpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkoZHBseXIpCmBgYAoKYGBge3J9CmxpYnJhcnkoUkNvbG9yQnJld2VyKQpgYGAKCgpgYGB7cn0KZ2FtZXNfc2FsZXNfZnVsbCA8LSByZWFkX2NzdigiZ2FtZXNfc2FsZXNfZnVsbF9jbGVhbmVkLmNzdiIpCmBgYAoKCmBgYHtyfQpnYW1lc19zYWxlc19mdWxsX3RvdGFsIDwtIHJlYWRfY3N2KCJnYW1lc19zYWxlc19mdWxsX3RvdGFsX2NsZWFuZWQuY3N2IikKYGBgCgpEdWUgdG8gdGhlIHNpemUgb2YgdGhlIGZpbGUgSSB3aWxsIGZvY3Vzb24gb24gdGhlIHRvcCBzYWxlcyBmb3IgYW5hbHlzaXMKYGBge3J9CmdhbWVzX3NhbGVzX2Z1bGxfdG90YWxfdG9wXzIwMCA8LSBnYW1lc19zYWxlc19mdWxsX3RvdGFsICU+JQogIGFycmFuZ2UoZGVzYyh0b3RhbF9nbG9iYWxfc2FsZXMpKSAlPiUKICBzbGljZSgxOjIwMCkKZ2FtZXNfc2FsZXNfZnVsbF90b3RhbF90b3BfMjAwCmBgYAoKYGBge3J9CmdhbWVzX3NhbGVzX2Z1bGxfdG90YWxfdG9wXzUwIDwtIGdhbWVzX3NhbGVzX2Z1bGxfdG90YWwgJT4lCiAgYXJyYW5nZShkZXNjKHRvdGFsX2dsb2JhbF9zYWxlcykpICU+JQogIHNsaWNlKDE6NTApCmdhbWVzX3NhbGVzX2Z1bGxfdG90YWxfdG9wXzUwCmBgYAoKCmBgYHtyfQpzdW1tYXJ5KGdhbWVzX3NhbGVzX2Z1bGxfdG90YWwpCmBgYAoKIyMjIyMgMS4gVXNlIGdyYXBoCmBgYHtyfQpnYW1lc19zYWxlc19mdWxsX3RvdGFsX3RvcF8yMDAgJT4lCiAgZ3JvdXBfYnkoZ2VucmUpICU+JSAKICBnZ3Bsb3QoYWVzKHggPSBnZW5yZSwgZmlsbCA9IGdlbnJlKSApICsKICBnZW9tX2JhcigpICsKICBsYWJzKHRpdGxlID0gIkdhbWVzIGNvdW50IGJ5IGdlbnJlIikgKwogIGxhYnMoeCA9ICJHZW5yZSIpICsKICBsYWJzKHkgPSAiTnVtYmVyIG9mIEdhbWVzIikgKwogIGxhYnMoZmlsbCA9ICJHZW5yZSIpICsKICBjb29yZF9mbGlwKCkKCmBgYAoKYGBge3J9CmdhbWVzX3NhbGVzX2Z1bGxfdG90YWxfdG9wXzIwMCAlPiUKICBncm91cF9ieShnZW5yZSkgJT4lIAogIGdncGxvdChhZXMoeCA9IGdlbnJlLCBmaWxsID0gZ2VucmUpICkgKwogIGdlb21fYmFyKCkgKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbj0ibm9uZSIpICsKICBsYWJzKHRpdGxlID0gIkdhbWVzIGNvdW50IGJ5IGdlbnJlIikgKwogIGxhYnMoeCA9ICJHZW5yZSIpICsKICBsYWJzKHkgPSAiTnVtYmVyIG9mIEdhbWVzIikgKwogIGxhYnMoZmlsbCA9ICJHZW5yZSIpICsKICBjb29yZF9mbGlwKCkKZ2dzYXZlKCJnZW5yZV9jb3VudC5wbmciKQpgYGAKCgoKIyMjIyMgMi4gVXNlIGdyYXBoID8/Pz8gCmBgYHtyfQpnYW1lc19zYWxlc19mdWxsX3RvdGFsX3RvcF8yMDAgJT4lIAogIGdyb3VwX2J5KHB1Ymxpc2hlcikgJT4lIAogIGdncGxvdChhZXMoeCA9IGdlbnJlLCBmaWxsID0gcHVibGlzaGVyKSApICsKICBnZW9tX2JhcigpICsKICBsYWJzKHRpdGxlID0gIkdhbWVzIGNvdW50IGJ5IHB1Ymxpc2hlciBhbmQgZ2VucmUiKSArCiAgbGFicyh4ID0gIkdlbnJlIikgKwogIGxhYnMoeSA9ICJOdW1iZXIgb2YgR2FtZXMiKSArCiAgbGFicyhmaWxsID0gIlB1Ymxpc2hlciIpICsKICBjb29yZF9mbGlwKCkKYGBgCgojIyMjIyAKYGBge3J9CmdhbWVzX3NhbGVzX2Z1bGxfdG90YWxfdG9wXzIwMCAlPiUgCiAgZ3JvdXBfYnkoZGV2ZWxvcGVyKSAlPiUgCiAgZ2dwbG90KGFlcyh4ID0gZ2VucmUsIGZpbGwgPSBkZXZlbG9wZXIpICkgKwogIGdlb21fYmFyKCkgKwogIGxhYnModGl0bGUgPSAiR2FtZXMgY291bnQgYnkgZGV2ZWxvcGVyIGFuZCBnZW5yZSIpICsKICBsYWJzKHggPSAiR2VucmUiKSArCiAgbGFicyh5ID0gIk51bWJlciBvZiBHYW1lcyIpICsKICBsYWJzKGZpbGwgPSAiRGV2ZWxvcGVyIikgKwogIGNvb3JkX2ZsaXAoKQoKYGBgCgpgYGB7cn0KZ2FtZXNfc2FsZXNfZnVsbF90b3RhbF90b3AgPC0gZ2FtZXNfc2FsZXNfZnVsbF90b3RhbCAlPiUKICBhcnJhbmdlKGRlc2ModG90YWxfZ2xvYmFsX3NhbGVzKSkgJT4lCiAgc2xpY2UoMTo1MCkKZ2FtZXNfc2FsZXNfZnVsbF90b3RhbF90b3AKCmBgYAoKIyMjIyMgMy4gVXNlIGdyYXBoCmBgYHtyfQpnYW1lc19zYWxlc19mdWxsX3RvdGFsX3RvcCAlPiUgCiAgZ3JvdXBfYnkoZGV2ZWxvcGVyKSAlPiUgCiAgZ2dwbG90KGFlcyh4ID0gZ2VucmUsIGZpbGwgPSBkZXZlbG9wZXIpICkgKwogIGdlb21fYmFyKCkgKwogIGxhYnModGl0bGUgPSAiR2FtZXMgY291bnQgYnkgZGV2ZWxvcGVyIGFuZCBnZW5yZSIpICsKICBsYWJzKHggPSAiR2VucmUiKSArCiAgbGFicyh5ID0gIk51bWJlciBvZiBHYW1lcyIpICsKICBsYWJzKGZpbGwgPSAiRGV2ZWxvcGVyIikgKwogIGNvb3JkX2ZsaXAoKQpnZ3NhdmUoImdlbnJlX2RldmVsb3Blci5wbmciKQpgYGAKCiMjIyMjIyMjIyMgCgojIyMjIyAzLjUgVXNlIGdyYXBoIC0gR2VucmUgYW5kIERldiBmbGlwcGVkIApgYGB7cn0KZ2FtZXNfc2FsZXNfZnVsbF90b3RhbF90b3AgJT4lIAogIGdyb3VwX2J5KGRldmVsb3BlcikgJT4lIAogIGdncGxvdChhZXMoeCA9IGRldmVsb3BlciwgZmlsbCA9IGdlbnJlKSApICsKICBnZW9tX2JhcigpICsKICBsYWJzKHRpdGxlID0gIkdhbWVzIGNvdW50IGJ5IGRldmVsb3BlciBhbmQgZ2VucmUiKSArCiAgbGFicyh4ID0gIkRldmVsb3BlciIpICsKICBsYWJzKHkgPSAiTnVtYmVyIG9mIEdhbWVzIikgKwogIGxhYnMoZmlsbCA9ICJHZW5yZSIpICsKICBjb29yZF9mbGlwKCkKZ2dzYXZlKCJkZXZlbG9wZXJfZ2VucmUucG5nIikKYGBgCgoKCmBgYHtyfQpnYW1lc19zYWxlc19mdWxsX3RvdGFsX3RvcF9nYW1lcyA8LSBnYW1lc19zYWxlc19mdWxsX3RvdGFsICU+JQogIGFycmFuZ2UoZGVzYyh0b3RhbF9nbG9iYWxfc2FsZXMpKSAlPiUKICBzbGljZSgxOjIwKQpnYW1lc19zYWxlc19mdWxsX3RvdGFsX3RvcF9nYW1lcwpgYGAKCiMjIyMjIDQuIFVzZSBncmFwaApgYGB7cn0KZ2FtZXNfc2FsZXNfZnVsbF90b3RhbF90b3BfZ2FtZXMgJT4lIAogIGdyb3VwX2J5KG5hbWUpICU+JSAKICBnZ3Bsb3QoYWVzKHggPSBuYW1lLCB5ID0gdG90YWxfZ2xvYmFsX3NhbGVzLCBmaWxsID0gbmFtZSkpICsKICBnZW9tX2NvbCgpICsKICBsYWJzKHRpdGxlID0gIlRvcCAyMCBnYW1lcyBzYWxlcyBieSBuYW1lIikgKwogIGxhYnMoeCA9ICJOYW1lIikgKwogIGxhYnMoeSA9ICJUb3AgMjAgZ2xvYmFsIHNhbGVzIikgKwogIGxhYnMoZmlsbCA9ICJOYW1lIikgKwogIGNvb3JkX2ZsaXAoKQpnZ3NhdmUoInRvcDIwX2dhbWVzLnBuZyIpCmBgYAoKYGBge3J9CmdhbWVzX3NhbGVzX2Z1bGxfdG90YWxfdG9wX2dhbWVzICU+JSAKICBncm91cF9ieShuYW1lKSAlPiUgCiAgZ2dwbG90KGFlcyh4ID0gbmFtZSwgeSA9IHRvdGFsX2dsb2JhbF9zYWxlcywgZmlsbCA9IG5hbWUpKSArCiAgZ2VvbV9jb2woKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uPSJub25lIikgKwogIGxhYnModGl0bGUgPSAiVG9wIDIwIGdhbWVzIHNhbGVzIGJ5IG5hbWUiKSArCiAgbGFicyh4ID0gIk5hbWUiKSArCiAgbGFicyh5ID0gIlRvcCAyMCBnbG9iYWwgc2FsZXMiKSArCiAgbGFicyhmaWxsID0gIk5hbWUiKSArCiAgY29vcmRfZmxpcCgpCmdnc2F2ZSgidG9wMjBfZ2FtZXMucG5nIikKCmBgYAoKYGBge3J9CmdhbWVzX3NhbGVzX2Z1bGxfdG90YWxfdG9wX2dhbWVzX2dlbnJlIDwtIGdhbWVzX3NhbGVzX2Z1bGxfdG90YWwgJT4lCiAgYXJyYW5nZShkZXNjKHRvdGFsX2dsb2JhbF9zYWxlcykpICU+JQogIHNsaWNlKDE6NDApCmdhbWVzX3NhbGVzX2Z1bGxfdG90YWxfdG9wX2dhbWVzX2dlbnJlCmBgYAoKYGBge3J9CmdhbWVzX3NhbGVzX2Z1bGxfdG90YWxfdG9wX2dhbWVzX2dlbnJlX3NlbGVjdCA8LSBnYW1lc19zYWxlc19mdWxsX3RvdGFsICU+JQogIGFycmFuZ2UoZGVzYyh0b3RhbF9nbG9iYWxfc2FsZXMpKSAlPiUKICBzZWxlY3QocmFuaywgbmFtZSwgZ2VucmUsIHBsYXRmb3JtLCB0b3RhbF9nbG9iYWxfc2FsZXMpICU+JQogIHNsaWNlKDE6NTApCmdhbWVzX3NhbGVzX2Z1bGxfdG90YWxfdG9wX2dhbWVzX2dlbnJlX3NlbGVjdApgYGAKCmBgYHtyfQpnYW1lc19zYWxlc19mdWxsX3RvdGFsX3RvcF9nYW1lc19nZW5yZSAlPiUgCiAgZ3JvdXBfYnkobmFtZSkgJT4lIAogIGdncGxvdChhZXMoeCA9IG5hbWUsIHkgPSB0b3RhbF9nbG9iYWxfc2FsZXMsIGZpbGwgPSBnZW5yZSkpICsKICBnZW9tX2NvbCgpICsKICBsYWJzKHRpdGxlID0gIlRvcCA0MCBnYW1lcyBzYWxlcyBieSBuYW1lIGFuZCBnZW5yZSIpICsKICBsYWJzKHggPSAiTmFtZSIpICsKICBsYWJzKHkgPSAiVG9wIDQwIGdsb2JhbCBzYWxlcyIpICsKICBsYWJzKGZpbGwgPSAiR2VucmUiKSArCiAgY29vcmRfZmxpcCgpCmdnc2F2ZSgidG9wNDBfZ2FtZXNfbmFtZV9nZW5yZS5wbmciKQoKYGBgCgprLW1lYW5zCmBgYHtyfQojZ2FtZXNfc2FsZXNfZnVsbF90b3RhbF90b3BfZ2FtZXNfZ2VucmUgJT4lIAogIyB1bm5lc3QoY29scyA9IGMoYXVnbWVudGVkKSkgJT4lCiAgI2ZpbHRlcihrID09IDIpICU+JQojIGdncGxvdChhZXMoeCA9IG11cmRlciwgeSA9IGFzc2F1bHQsIGNvbG91ciA9IC5jbHVzdGVyLCBsYWJlbCA9IC5yb3duYW1lcykpICsKICMgZ2VvbV9wb2ludChhZXMoY29sb3IgPSAuY2x1c3RlcikpICsKICMgZ2VvbV90ZXh0KGhqdXN0ID0gMCwgdmp1c3QgPSAtIDAuNSwgc2l6ZSA9IDMpCmBgYAoKCgojIyMjIyA1LiBVc2UgZ3JhcGgKYGBge3J9CmdhbWVzX3NhbGVzX2Z1bGxfdG90YWxfdG9wXzIwMCAlPiUgCiAgZ3JvdXBfYnkoZGV2ZWxvcGVyKSAlPiUgCiAgZ2dwbG90KGFlcyh4ID0gZ2VucmUsIGZpbGwgPSBwbGF0Zm9ybSkpICsKICBnZW9tX2JhcigpICsKICBsYWJzKHRpdGxlID0gIkdhbWVzIGNvdW50IGJ5IHBsYXRmb3JtIGFuZCBnZW5yZSIpICsKICBsYWJzKHggPSAiR2VucmUiKSArCiAgbGFicyh5ID0gIk51bWJlciBvZiBHYW1lcyIpICsKICBsYWJzKGZpbGwgPSAiUGxhdGZvcm0iKSArCiAgY29vcmRfZmxpcCgpCmdnc2F2ZSgiY291bnRfcGxhdGZvcm1fZ2VucmUucG5nIikKYGBgCgoKIyMjIyMgNi4gVXNlIGdyYXBoIC0gZ3JhcGggNS4gc3dhcHBlZCB1c2UgNSBPUiA2CmBgYHtyfQpnYW1lc19zYWxlc19mdWxsX3RvdGFsX3RvcF8yMDAgJT4lIAogIGdyb3VwX2J5KGRldmVsb3BlcikgJT4lIAogIGdncGxvdChhZXMoeCA9IHBsYXRmb3JtLCBmaWxsID0gZ2VucmUpKSArCiAgZ2VvbV9iYXIoKSArCiAgbGFicyh0aXRsZSA9ICJHYW1lcyBjb3VudCBieSBnZW5yZSBhbmQgcGxhdGZvcm0iKSArCiAgbGFicyh4ID0gIlBsYXRmb3JtIikgKwogIGxhYnMoeSA9ICJOdW1iZXIgb2YgR2FtZXMiKSArCiAgbGFicyhmaWxsID0gIkdlbnJlIikgKwogIGNvb3JkX2ZsaXAoKQpnZ3NhdmUoImNvdW50X2dlbnJlX3BsYXRmb3JtLnBuZyIpCmBgYAoKQWxyZWFkeSB1c2VkIGFzIGdyYXBoIDEKYGBge3J9CmdhbWVzX3NhbGVzX2Z1bGxfdG90YWxfdG9wXzIwMCAlPiUgCiAgZ3JvdXBfYnkoZ2VucmUpICU+JSAKICBnZ3Bsb3QoYWVzKHggPSBnZW5yZSwgZmlsbCA9IGdlbnJlKSkgKwogIGdlb21fYmFyKCkgKwogIGxhYnModGl0bGUgPSAiR2FtZXMgY291bnQgYnkgZ2VucmUiKSArCiAgbGFicyh4ID0gIkdlbnJlIikgKwogIGxhYnMoeSA9ICJOdW1iZXIgb2YgR2FtZXMiKSArCiAgbGFicyhmaWxsID0gIkdlbnJlIikgKwogIGNvb3JkX2ZsaXAoKQpnZ3NhdmUoImdlbnJlX2NvdW50LnBuZyIpCmBgYAoKR2FtZXMgYnkgcGxhdGZvcm0KYGBge3J9CmdhbWVzX3NhbGVzX2Z1bGxfdG90YWxfdG9wXzIwMCAlPiUgCiAgZ3JvdXBfYnkoZ2VucmUpICU+JSAKICBnZ3Bsb3QoYWVzKHggPSBwbGF0Zm9ybSwgZmlsbCA9IHBsYXRmb3JtKSApICsKICBnZW9tX2JhcigpICsKICBsYWJzKHRpdGxlID0gIkdhbWVzIGNvdW50IGJ5IFBsYXRmb3JtIikgKwogIGxhYnMoeCA9ICJQbGF0Zm9ybSIpICsKICBsYWJzKHkgPSAiTnVtYmVyIG9mIEdhbWVzIikgKwogIGxhYnMoZmlsbCA9ICJQbGF0Zm9ybSIpICsKICBjb29yZF9mbGlwKCkKCmBgYAoKCiMjIyMjIDcuIFVzZSBncmFwaApgYGB7cn0KZ2FtZXNfc2FsZXNfZnVsbF90b3RhbF90b3BfMjAwICU+JSAKICBncm91cF9ieShnZW5yZSkgJT4lIAogIGdncGxvdChhZXMoeCA9IHBsYXRmb3JtLCBmaWxsID0gcGxhdGZvcm0pICkgKwogIGdlb21fYmFyKCkgKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbj0ibm9uZSIpICsKICBsYWJzKHRpdGxlID0gIkdhbWVzIGNvdW50IGJ5IFBsYXRmb3JtIikgKwogIGxhYnMoeCA9ICJQbGF0Zm9ybSIpICsKICBsYWJzKHkgPSAiTnVtYmVyIG9mIEdhbWVzIikgKwogIGxhYnMoZmlsbCA9ICJQbGF0Zm9ybSIpICsKICBjb29yZF9mbGlwKCkKZ2dzYXZlKCJwbGF0Zm9ybV9jb3VudC5wbmciKQpgYGAKCgpHYW1lcyBieSByZWdpb24gLSBnbG9iYWwgbWFya2V0CgpgYGB7cn0KZ2FtZXNfc2FsZXNfZnVsbF9sb25nZXIgJT4lIAogIGdyb3VwX2J5KGdlbnJlKSAlPiUgCiAgZ2dwbG90KGFlcyh4ID0gc2FsZXNfcmVnaW9uLCB5ID0gc2FsZXNfcmVnaW9uX21pbGxpb25zKSApICsKICBnZW9tX2xpbmUoKSArCiAgbGFicyh0aXRsZSA9ICJHZW9ncmFwaGljIGJyZWFrZG93biBvZiBHbG9iYWwgU2FsZXMiKSArCiAgbGFicyh4ID0gIlNwZWNpZmljIGdsb2JhbCBtYXJrZXQiKSArCiAgbGFicyh5ID0gIlNhbGVzIChtaWxsaW9ucykiKSArCiAgbGFicyhmaWxsID0gIkdlbnJlIikgKwogIGNvb3JkX2ZsaXAoKQoKYGBgCgpgYGB7cn0KZ2FtZXNfc2FsZXNfZnVsbF90b3RhbF90b3BfMjAwICU+JSAKICBncm91cF9ieShnZW5yZSkgJT4lIAogIGdncGxvdChhZXMoeCA9IHRvdGFsX2dsb2JhbF9zYWxlcywgZmlsbCA9IGdlbnJlKSApICsKICBnZW9tX2JhcigpICsKICBsYWJzKHRpdGxlID0gIkdlb2dyYXBoaWMgYnJlYWtkb3duIG9mIEdsb2JhbCBTYWxlcyIpICsKICBsYWJzKHggPSAiU2FsZXMgKG1pbGxpb25zKSIpICsKICBsYWJzKHkgPSAiU3BlY2lmaWMgZ2xvYmFsIG1hcmtldCIpICsKICBsYWJzKGZpbGwgPSAiR2VucmUiKSArCiAgY29vcmRfZmxpcCgpCgpgYGAKCgojIyMgSGlkZSB0aGUgbGVnZW5kCmBgYHtyfQpnYW1lc19zYWxlc19mdWxsX3RvdGFsX3RvcF8yMDAgJT4lIAogIGdyb3VwX2J5KGdlbnJlKSAlPiUgCiAgZ2dwbG90KGFlcyh4ID0gdG90YWxfZ2xvYmFsX3NhbGVzLCBmaWxsID0gZ2VucmUpKSArCiAgZ2VvbV9iYXIoKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uPSJub25lIikgKwogIGxhYnModGl0bGUgPSAiR2VvZ3JhcGhpYyBicmVha2Rvd24gb2YgR2xvYmFsIFNhbGVzIikgKwogIGxhYnMoeCA9ICJTYWxlcyAobWlsbGlvbnMpIikgKwogIGxhYnMoeSA9ICJTcGVjaWZpYyBnbG9iYWwgbWFya2V0IikgKwogIGxhYnMoZmlsbCA9ICJHZW5yZSIpICsKICBjb29yZF9mbGlwKCkKCmBgYAoKCmBgYHtyfQpnYW1lc19zYWxlc19mdWxsX3RvdGFsX3RvcF8yMDAgJT4lIAogIGdhdGhlcigiaWQiLCAidmFsdWUiLCAxMzoxNikgJT4lIAogIGdncGxvdCguLCBhZXModG90YWxfZ2xvYmFsX3NhbGVzLCB2YWx1ZSkpKwogIGdlb21fcG9pbnQoKSsKICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBzZT1GQUxTRSwgY29sb3I9ImJsYWNrIikrCiAgZmFjZXRfd3JhcCh+aWQpCmBgYAoKYGBge3J9CmdhbWVzX3NhbGVzX2Z1bGxfbG9uZ2VyIDwtIHJlYWRfY3N2KCJnYW1lc19zYWxlc19mdWxsX2xvbmdlci5jc3YiKQpgYGAKCgoKYGBge3J9CmdhbWVzX3NhbGVzX2Z1bGxfYmluZF90b3RhbF9sb25nZXIgPC0gcmVhZF9jc3YoImdhbWVzX3NhbGVzX2Z1bGxfYmluZF90b3RhbF9sb25nZXIuY3N2IikKYGBgCgpgYGB7cn0KZ2FtZXNfc2FsZXNfZnVsbF9iaW5kX3RvdGFsX2xvbmdlciAlPiUKICBncm91cF9ieShzYWxlc19yZWdpb24sIHllYXJfZGF0YSkgJT4lCiAgc3VtbWFyaXNlKFRvdGFsID0gc3VtKHNhbGVzX3JlZ2lvbl9taWxsaW9ucywgbmEucm0gPSBUUlVFKSkKYGBgCgoKCgpgYGB7cn0KZ2FtZXNfc2FsZXNfZnVsbF9iaW5kX3RvdGFsX2xvbmdlciAlPiUKICBncm91cF9ieShzYWxlc19yZWdpb24sIHllYXJfZGF0YSkgJT4lCiAgc3VtbWFyaXNlKFRvdGFsID0gc3VtKHNhbGVzX3JlZ2lvbl9taWxsaW9ucywgbmEucm0gPSBUUlVFKSkgJT4lCiAgZ2dwbG90KGFlcyh4ID0gc2FsZXNfcmVnaW9uLCB5ID0gVG90YWwpKSArCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIpICsKICBsYWJzKHRpdGxlID0gIlRvdGFsIGdvYmFsIHNhbGVzIGJ5IHJlZ2lvbiIpICsKICBsYWJzKHggPSAiR2xvYmFsIG1hcmtldCByZWdpb24iKSArCiAgbGFicyh5ID0gIlRvdGFsIHNhbGVzIChtaWxsaW9ucykiKSArCiAgZmFjZXRfd3JhcCh+eWVhcl9kYXRhKQoKYGBgCgpgYGB7cn0KZ2dwbG90KGdhbWVzX3NhbGVzX2Z1bGxfYmluZF90b3RhbF9sb25nZXIsIGFlcyhzYWxlc19yZWdpb24sIHRvdGFsX2dsb2JhbF9zYWxlcykpICsKICBnZW9tX2JveHBsb3QoKSArCiAgbGFicyh0aXRsZSA9ICJEaXN0cmlidXRpb24gb2Ygc2FsZXMgYnkgZ2VucmUiKSArCiAgbGFicyh4ID0gIkdlbnJlIikgKwogIGxhYnMoeSA9ICJTYWxlcyAobWlsbGlvbnMpIikgKwogICBjb29yZF9mbGlwKCkKYGBgCgoKIyMjIyMgOC4gVXNlIGdyYXBoCgoKYGBge3J9CmdhbWVzX3NhbGVzX2Z1bGxfYmluZF90b3RhbF9sb25nZXJfcmVnaW9uICU+JQogIGdncGxvdChhZXMoeCA9IHNhbGVzX3JlZ2lvbiwgeSA9IHNhbGVzX3JlZ2lvbl9taWxsaW9ucykpICsKICBnZW9tX2NvbCgpICsKICBsYWJzKHRpdGxlID0gIlRvdGFsIGdvYmFsIHNhbGVzIGJ5IHJlZ2lvbiIpICsKICBsYWJzKHggPSAiR2xvYmFsIG1hcmtldCByZWdpb24iKSArCiAgbGFicyh5ID0gIlRvdGFsIHNhbGVzIChtaWxsaW9ucykiKSArCiAgc2NhbGVfZmlsbF9icmV3ZXIgKCkgKwogIGZhY2V0X3dyYXAofnllYXJfZGF0YSkKYGBgCgoKYGBge3J9CmdhbWVzX3NhbGVzX2Z1bGxfYmluZF90b3RhbDwtIHJlYWRfY3N2KCJnYW1lc19zYWxlc19mdWxsX2JpbmRfdG90YWwuY3N2IikKYGBgCgoKIyMjIyMgRG9udCB1c2UKYGBge3J9CmdhbWVzX3NhbGVzX2Z1bGxfYmluZF90b3RhbF9sb25nZXIgJT4lCiAgZ2dwbG90KGFlcyh4ID0gc2FsZXNfcmVnaW9uLCB5ID0gc2FsZXNfcmVnaW9uX21pbGxpb25zLCBmaWxsID0gZ2VucmUpKSArCiAgZ2VvbV9jb2woKSArCiAgbGFicyh0aXRsZSA9ICJUb3RhbCBnbG9iYWwgc2FsZXMgYnkgcmVnaW9uIikgKwogIGxhYnMoeCA9ICJUb3RhbCBzYWxlcyIpICsKICBsYWJzKHkgPSAiR2xvYmFsIG1hcmtldCByZWdpb24iKQpnZ3NhdmUoInNhbGVzX3JlZ2lvbl9nZW5yZS5wbmciKQpgYGAKCgpYWFhYWFhYWCBXUk9ORyBEUwpgYGB7cn0KZ2FtZXNfc2FsZXNfZnVsbF9iaW5kX3RvdGFsX2xvbmdlciAlPiUKICBnZ3Bsb3QoYWVzKHggPSBnZW5yZSwgeSA9IHNhbGVzX3JlZ2lvbl9taWxsaW9ucywgZmlsbCA9IHNhbGVzX3JlZ2lvbikpICsKICBnZW9tX2NvbCgpICsKICBsYWJzKHRpdGxlID0gIlRvdGFsIGdsb2JhbCBzYWxlcyBieSBnZW5yZSBhbmQgcmVnaW9uIikgKwogIGxhYnMoeCA9ICJHbG9iYWwgbWFya2V0IHJlZ2lvbiIpICsKICBsYWJzKHkgPSAiVG90YWwgc2FsZXMiKSArCiAgY29vcmRfZmxpcCgpCmdnc2F2ZSgic2FsZXNfZ2VucmVfcmVnaW9uLnBuZyIpCmBgYAoKCiMjIyMjIyMgQ29ycmVjdCBEUwpgYGB7cn0KZ2FtZXNfc2FsZXNfZnVsbF9iaW5kX3RvdGFsX2xvbmdlciAlPiUKICBncm91cF9ieShzYWxlc19yZWdpb24sIHllYXJfZGF0YSwgZ2VucmUsIHNhbGVzX3JlZ2lvbl9taWxsaW9ucykgJT4lCiAgc3VtbWFyaXNlKFRvdGFsID0gc3VtKHNhbGVzX3JlZ2lvbl9taWxsaW9ucywgbmEucm0gPSBUUlVFKSkgJT4lCiAgZ2dwbG90KGFlcyh4ID0gZ2VucmUsIHkgPSBzYWxlc19yZWdpb25fbWlsbGlvbnMsIGZpbGwgPSBzYWxlc19yZWdpb24pKSArCiAgZ2VvbV9jb2woKSArCiAgbGFicyh0aXRsZSA9ICJUb3RhbCBnbG9iYWwgc2FsZXMgYnkgZ2VucmUgYW5kIHJlZ2lvbiIpICsKICBsYWJzKHggPSAiR2xvYmFsIG1hcmtldCByZWdpb24iKSArCiAgbGFicyh5ID0gIlRvdGFsIHNhbGVzIikgKwogIGNvb3JkX2ZsaXAoKQpnZ3NhdmUoInNhbGVzX2dlbnJlX3JlZ2lvbi5wbmciKQpgYGAKCgoKCiMjIyMjIDkuIFVzZSBncmFwaApHYW1lcyBtZWFuIChtYXgvIG1pbikgc2FsZXMKYGBge3J9CmdncGxvdChnYW1lc19zYWxlc19mdWxsX3RvdGFsX3RvcF8yMDAsIGFlcyhnZW5yZSwgdG90YWxfZ2xvYmFsX3NhbGVzKSkgKwogIGdlb21fYm94cGxvdCgpICsKICBsYWJzKHRpdGxlID0gIkRpc3RyaWJ1dGlvbiBvZiBzYWxlcyBieSBnZW5yZSIpICsKICBsYWJzKHggPSAiR2VucmUiKSArCiAgbGFicyh5ID0gIlNhbGVzIChtaWxsaW9ucykiKSArCiAgIGNvb3JkX2ZsaXAoKQpnZ3NhdmUoImRpc3RyaWJ1dGlvbl9zYWxlc19ieV9nZW5yZS5wbmciKQpgYGAKCiMjIyMjIDEwLiBVc2UgZ3JhcGgKYGBge3J9CmdncGxvdChnYW1lc19zYWxlc19mdWxsX3RvdGFsX3RvcF8yMDAsIGFlcyhwbGF0Zm9ybSwgdG90YWxfZ2xvYmFsX3NhbGVzKSkgKwogIGdlb21fYm94cGxvdCgpICsKICBsYWJzKHRpdGxlID0gIkRpc3RyaWJ1dGlvbiBvZiBzYWxlcyBieSBwbGF0Zm9ybSIpICsKICBsYWJzKHggPSAiUGxhdGZvcm0iKSArCiAgbGFicyh5ID0gIlNhbGVzIChtaWxsaW9ucykiKSArCiAgIGNvb3JkX2ZsaXAoKQpnZ3NhdmUoImRpc3RyaWJ1dGlvbl9zYWxlc19ieV9wbGF0Zm9ybS5wbmciKQpgYGAKCgoKCnNoaXBwZWQgLyBjcml0aWMgc2NvcmUKYGBge3J9CgpgYGAKCgoKCgoKCgoKCgoK